package com.hzit.pay.web.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.hzit.pay.web.mapper.PaySerialMapper;
import com.hzit.pay.web.mapper.RefundApplyMapper;
import com.hzit.pay.web.model.PaySerial;
import com.hzit.pay.web.model.RefundApply;
import com.hzit.pay.web.service.IRefundService;
import com.hzit.payweb.api.enums.PayStatusEnum;
import com.hzit.pay.web.iClient.IAliapyFrontClient;
import com.hzit.payweb.api.req.RefundReq;
import com.hzit.payweb.api.resp.RespVo;
import com.hzit.payweb.api.resp.data.RefundRespData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 退款相关业务接口实现类
 */
@Service
public class RefundServiceImpl implements IRefundService {

    private static final Logger logger = LoggerFactory.getLogger(RefundServiceImpl.class);

    @Autowired
    private PaySerialMapper paySerialMapper;

    @Autowired
    private RefundApplyMapper refundApplyMapper;

    @Autowired
    private IAliapyFrontClient aliapyFrontClient;

    @Override
    public RespVo<RefundRespData> refund(RefundReq refundReq) {

        //1.验证签名

        //2.检查是否满足退款要求： 是否超过约定时间，是否多次退款，退款次数不能超过50次
        PaySerial paySerial = paySerialMapper.queryBySerialNoAndOrderId(refundReq.getPaySerialNo(),refundReq.getMchOrderId());
        if(ObjectUtils.isEmpty(paySerial)){
            logger.info("流水号：{}，商户订单号：在db中没有找到对应记录",refundReq.getPaySerialNo(),refundReq.getMchOrderId());
            return RespVo.returnFail(-1,"在db中没有找到对应记录");
        }

        if(PayStatusEnum.PAY_SUCCESS.getCode()!= Integer.parseInt(paySerial.getStatus())){
            logger.info("流水号：{}，商户订单号：在db中没有找到支付成功的记录",refundReq.getPaySerialNo(),refundReq.getMchOrderId());
            return RespVo.returnFail(-1,"在db中没有找到支付成功的记录");
        }

        Date successTime = paySerial.getPaySuccessTime(); //对比 是否超过约定时
        //TODO

        BigDecimal payAmt = paySerial.getPayAmt();

        List<RefundApply>  applyList = refundApplyMapper.querySuccessList(refundReq.getPaySerialNo(),refundReq.getPaySerialNo());
        if(applyList.size()>50){
            return RespVo.returnFail(-1,"退款笔数不能超过50");
        }

        BigDecimal refundedAmt = new BigDecimal(0);
        if(!CollectionUtils.isEmpty(applyList)){

            for (RefundApply refundApply:applyList){
                refundedAmt = refundedAmt.add(refundApply.getRefundAmt());
            }
        }

        BigDecimal amout = refundedAmt.add(new BigDecimal(refundReq.getRefundAmt()));
        if ((payAmt.subtract(amout).compareTo( new BigDecimal(0))<0)){
            return RespVo.returnFail(-1,"退款金额不能超支付金额");
        }

        //生成退款流水

        RefundApply refundApply = new RefundApply();

        Date nowTime = new Date();

        Snowflake snowflake = new Snowflake(10,9);

        String refundId = snowflake.nextIdStr();
        refundApply.setRefundSerialNo(refundId); //分布式唯一id
        refundApply.setBank(refundReq.getBank());
        refundApply.setCreateBy("system");
        refundApply.setCreateTime(nowTime);
        refundApply.setOriMchOrederId(refundReq.getMchOrderId());
        refundApply.setOriPaySerialNo(refundReq.getPaySerialNo());
        refundApply.setMchId(refundReq.getBank());
        refundApply.setPayWay(refundReq.getRefundAmt());
        refundApply.setPayWay(refundReq.getPayWay());
        refundApply.setRefundStatus("1");  //状态枚举
        refundApplyMapper.insertSelective(refundApply);

        //2.调用相关退款接口,单笔实时退款
        if ("alipay".equals(refundReq.getBank())){

           RespVo respVo  = aliapyFrontClient.alipayRefundAmt(refundReq.getPaySerialNo(),refundReq.getRefundAmt(),refundId);

            //3.解析退款回调，更新，退款流水 TODO
            if(respVo.getCode() ==0){
                RefundRespData refundRespData = new RefundRespData();

                refundRespData.setRefundStatus("0");
                RespVo respVo1 = RespVo.returnSuccess("请求成");
                respVo1.setData(refundRespData);
                return respVo1;
            }

            //4.返回给业务系统

        //批量退款, 每天晚上8点上传退款文件
        }else if("icbc".equals(refundReq.getBank())){

            //告诉用户，退款受理中

            RefundRespData refundRespData = new RefundRespData();

            RespVo respVo =RespVo.returnSuccess("请求成");

            refundRespData.setRefundStatus("1");
            refundRespData.setRefundDesc("退款受理中,几个工作日到你卡上");
            respVo.setData(refundRespData);
            return respVo;


            //每隔5分钟执行一次
        } else if("wechat".equals(refundReq.getBank())){

            //插入退款流水。

            RespVo respVo =RespVo.returnSuccess("请求成");
            RefundRespData refundRespData = new RefundRespData();


            //调用微信前支付服务

            //根据前置服务回来的结果更新状态为微信处理中。


            refundRespData.setRefundStatus("1");
            refundRespData.setRefundDesc("微信处理中");
            respVo.setData(refundRespData);




            return respVo;


        }

        return null;
    }
}
